#include <type.h>
#include <common.h>

TypeBuiltin TypeBuiltin::Void(kBuiltinVoid, 0, "void");
TypeBuiltin TypeBuiltin::Char(kBuiltinChar, 1, "char");
TypeBuiltin TypeBuiltin::Bool(kBuiltinBool, 1, "bool");
TypeBuiltin TypeBuiltin::Short(kBuiltinShort, 2, "short");
TypeBuiltin TypeBuiltin::Int(kBuiltinInt, 4, "int");
TypeBuiltin TypeBuiltin::Long(kBuiltinLong, 8, "long");
TypeBuiltin TypeBuiltin::Float(kBuiltinFloat, 4, "float");
TypeBuiltin TypeBuiltin::Double(kBuiltinDouble, 8, "double");

TypeArray::TypeArray(Type base, size_t dlen) : _base(base), _dlen(dlen), _size(sizeType(base) * dlen) {
}

TypeStruct::TypeStruct(std::vector<std::pair<Type, std::string>>& member) {
    size_t length = 0;
    for (auto& t : member) {
        size_t s = sizeType(t.first);
        if (s > 0) {
            size_t align = s > ALIGN_SIZE ? ALIGN_SIZE : s;
            length = (length + align - 1) & ~(align - 1);
        }
        _offset[t.second] = length;
        _member[t.second] = t.first;
        length += s;
    }
    _size = ((length + (ALIGN_SIZE-1)) & ~(ALIGN_SIZE-1));
}


size_t sizeType(Type type) {
  if (type.type() == typeid(TypeBuiltin)) return std::any_cast<TypeBuiltin>(type).size();
  if (type.type() == typeid(TypePointer)) return std::any_cast<TypePointer>(type).size();
  if (type.type() == typeid(TypeArray)) return std::any_cast<TypeArray>(type).size();
  if (type.type() == typeid(TypeStruct)) return std::any_cast<TypeStruct>(type).size();
  return 0;
}



size_t Align(size_t& length, Type type) {
    size_t len = sizeType(type);
    if (len > 0) {
        size_t agn = len > ALIGN_SIZE ? ALIGN_SIZE : len;
        length = (length + agn - 1) & ~(agn-1);
    }
    size_t res = length;
    length += len;
    return res;
}

